package com.macro.mall.tiny.modules.foster.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.macro.mall.tiny.common.api.CommonResult;
import com.macro.mall.tiny.modules.foster.mapper.AppointmentMapper;
import com.macro.mall.tiny.modules.foster.model.AlipayOrder;
import com.macro.mall.tiny.modules.foster.model.Appointment;
import com.macro.mall.tiny.modules.foster.model.Pet;
import com.macro.mall.tiny.modules.foster.model.Room;
import com.macro.mall.tiny.modules.foster.model.dto.PetAndTimeDTO;
import com.macro.mall.tiny.modules.foster.service.AppointmentService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static com.baomidou.mybatisplus.core.toolkit.IdWorker.getId;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zhuyi
 * @since 2024-04-03
 */
@Service
public class AppointmentServiceImpl extends ServiceImpl<AppointmentMapper, Appointment> implements AppointmentService {

    private static final Logger LOGGER = LoggerFactory.getLogger(AppointmentServiceImpl.class);

    @Autowired
    private AppointmentMapper appointmentMapper;

    /**
     * 根据房间id获取所有的预约时间
     *
     * @param id 房间ID，用于查询与该房间相关联的所有预约时间。
     * @return 返回一个包含所有不重复预约日期的列表。每个日期字符串的格式为"yyyy-MM-dd"。
     */
    @Override
    public CommonResult getTimeByRoomId(Long id) {
        // 创建查询包装器，用于指定查询条件
        QueryWrapper<Appointment> wrapper = new QueryWrapper<>();
        // 根据房间ID设置查询条件
        wrapper.eq("room_id", id);

        // 根据查询条件从数据库中获取所有预约信息
        List<Appointment> appointments = appointmentMapper.selectList(wrapper);

        // 创建一个列表，用于存储格式化后的日期字符串
        ArrayList<String> list = new ArrayList<>();

        // 遍历所有预约信息，为每个预约日期生成字符串并添加到列表中
        appointments.stream()
                .forEach(appointment -> {
                    // 日期格式化工具对象
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                    // 预约起始日期
                    Date d1 = appointment.getStartTime();
                    // 预约结束日期
                    Date d2 = appointment.getEndTime();
                    Date tmp = d1;
                    Calendar dd = Calendar.getInstance();
                    dd.setTime(d1);
                    // 循环遍历从起始日期到结束日期间的每一天，并添加到列表中
                    while (tmp.getTime() < d2.getTime()) {
                        tmp = dd.getTime();
                        list.add(sdf.format(tmp));
                        // 天数加1，用于获取下一天
                        dd.add(Calendar.DAY_OF_MONTH, 1);
                    }
                });

        // 从列表中移除重复的日期字符串
        list.stream()
                .distinct()
                .collect(Collectors.toList());

        // 记录日志，表示根据房间ID获取所有预约时间成功
        LOGGER.info("根据房间id获取所有的预约时间成功");

        // 返回成功结果，包含处理后的预约日期列表
        return CommonResult.success(list);
    }


    /**
     * 添加预约时间
     *
     * @param timeDTO 预约时间数据传输对象，包含预约的开始时间、结束时间和房间ID
     * @return 返回一个通用结果对象，包含操作成功与否的状态和消息
     */
    @Override
    public CommonResult addOrderTime(PetAndTimeDTO timeDTO) {
        // 创建一个新的预约实例并设置相关属性
        Appointment appointment = new Appointment();
        appointment.setId(getId());
        appointment.setStartTime(timeDTO.getStartTime());
        appointment.setEndTime(timeDTO.getEndTime());
        appointment.setRoomId(timeDTO.getRoomId());

        // 获取并设置宠物ID，这里的代码看起来像是重复的，应该之前已有获取ID的操作
        long petId = getId();
        appointment.setPetId(petId);

        // 将预约信息插入数据库
        appointmentMapper.insert(appointment);
        LOGGER.info("添加预约时间成功");

        // 返回成功结果，包含宠物ID和成功消息
        return CommonResult.success(petId, "添加预约时间成功");
    }


    /**
     * 分页查询预约信息
     *
     * @param pageNum 页码，表示需要查询的页数
     * @param pageSize 每页显示的数量
     * @return 返回一个封装了预约信息的Page对象，其中包含了当前页的预约记录和其他分页信息
     */
    @Override
    public Page<Appointment> pageAppointment(int pageNum,int pageSize) {
        try {
            // 初始化分页对象
            Page<Appointment> page2 = new Page<>(pageNum, pageSize);
            // 通过mapper进行分页查询
            Page<Appointment> page = appointmentMapper.selectPage(page2, null);

            // 遍历查询结果，补充房间名和宠物名，并根据订单状态更新预约状态
            page.getRecords().stream().forEach(appointment -> {
                // 补充房间名
                Room room = appointmentMapper.selectRoomByRoomId(appointment.getRoomId());
                appointment.setRoomName(room.getName());
                // 补充宠物名
                Pet pet = appointmentMapper.selectPetByPetId(appointment.getPetId());
                appointment.setPetName(pet.getName());
                // 根据宠物ID查询订单，并根据订单状态更新预约状态
                List<AlipayOrder> orders = appointmentMapper.selectOrder(appointment.getPetId());
                Date date = new Date();
                orders.stream().forEach(order -> {
                    appointment.setStatus(2); // 默认状态设置为2（回退）
                    // 如果当前时间在预约结束时间之前，根据订单状态更新预约状态
                    if (date.before(appointment.getEndTime())){
                        int status=appointmentMapper.selectOrderStatus(order.getId());
                        appointment.setStatus(status);
                    }
                });
                // 如果预约状态未被更新，则默认设置为1（已完成）
                if (appointment.getStatus()==null){
                    appointment.setStatus(1);
                }
            });
            return page;
        } catch (Exception e) {
            // 捕获异常，抛出运行时异常
            throw new RuntimeException(e);
        }
    }

}
